import Core.Gadget as Gadget
import Core.Config as Config
import datetime
import random
import math
import numpy as np
import pandas as pd
import Analysis.General as General
import Analysis.LearningFramework as LearningFramework
import Factors.CheckFactor

def CheckFactors(database):
    #
    factorName = "cashearningminusearning_lyr"
    factorName = "cashearningtoearning_lyr"
    factorName = "cashroic_lyr"
    factorName = "cashearningtoprice_lyr" # Problematic
    factorName = "FCFToTotalIncome_LYR"
    factorName = "FCFToTotalIncome_TTM"
    factorName = "Leverage"  # Problematic
    factorName = "CurrentRatio" # 非线性 Count锯齿状
    factorName = "AssetTurnover_LYR" # 非线性 Count锯齿状
    factorName = "AssetTurnover_TTM" # 非线性 Count锯齿状
    factorName = "ReceivableTurnover_LYR" # 非线性 Count锯齿状

    #
    Factors.CheckFactor.PlotFactor(database, factorName)
    #

    # ---某个时间点---
    datetime1 = datetime.datetime(2017, 12, 31)
    df = Factors.CheckFactor.PlotFactorProfile(database, factorName, datetime1)

    datetime1 = datetime.datetime(2000, 1, 1)
    datetime2 = datetime.datetime(2019, 6, 1)
    Factors.CheckFactor.PlotFactorProfileHistory2(database, datetime1, datetime2, factorName, dateTimeField="ReportDate")
    pass

def ExportFactors(database):
    datetime1 = datetime.datetime(2006, 1, 1)
    datetime2 = datetime.datetime(2019, 11, 1)

    # ---Instruments---
    # instruments = database.Find("Instruments", "Stock", {"Industry": "钢铁"})
    instruments = None

    # ---Export Files---
    # General.ExportDataFilesMultiPeriod(database, datetime1, datetime2, factors, instruments,
    #                                 profileFolderName="MultiFactor", rangeReturnFolderName=None)

    # ---Time Range---
    datatimeRanges = Gadget.GenerateTimeRange_HalfYear(datetime1, datetime2)
    for timeRange in datatimeRanges:
        begin = timeRange[0]
        end = timeRange[1]
        General.Profile_to_File(database, begin, factors, instruments=instruments, folderName="MultiFactor")
        # General.Profile_to_File(database, begin, factors, instruments=instruments, folderName=None)

def Train_SinglePeriod(database):
    # ---Run Model---
    datetime1 = datetime.datetime(2007, 5, 1)
    datetime2 = datetime.datetime(2019, 5, 1)
    LearningFramework.SinglePeriodTest(None, datetime1, datetime2, factors, instruments,
                                      profileFolderName="DuPont", rangeReturnFolderName="")

    # SinglePeriodTest(database, datetime1, datetime2, instruments, factors)

    # --- Loop Single Period---
    # datetimes = Gadget.GenerateTimeRange_Yearly(datetime1, datetime2)
    # for dt in datetimes:
    #     print(dt)
    #     LearningFramework.SinglePeriodTest(None, dt[0], dt[1], factors, instruments,
    #                                        profileFolderName="DuPont", rangeReturnFolderName="")

def Train(database, factors):
    #
    datetime1 = datetime.datetime(2007, 5, 1)
    datetime2 = datetime.datetime(2019, 5, 1)

    # ---Multi Period---
    # LearningFramework.MultiPeriodTest(None, datetime1, datetime2, factors,
    #                                   profileFolderName="MultiFactor", rangeReturnFolderName="HalfYear")
    # MonthBased2(database, datetime1, datetime2, instruments, factors)
    # SeasonBased(database, datetime1, datetime2, instruments, factors)

    #
    params = {}
    params["DropRedundantFields"] = True
    # params["KeepFields"] = ["Symbol", "DateTime", "Return", "ExcessReturn"]
    # params["KeepFields"] = ["Symbol", "DateTime"]
    params["ProcessY_Threshold"] = -0.1
    params["ProcessY_RiskAlpha"] = "Alpha"
    params["ProcessY_UseExcessReturn"] = True
    params["ProcessX"] = True
    params["ProcessX_Factors"] = False
    params["ProcessX_Outlier"] = True
    params["ProcessX_Normalization"] = True

    # 钢铁 煤炭 基础化工 有色金属 建材
    instruments = database.Find("Instruments", "Stock", {"Industry": "建材"})
    params["Instruments"] = instruments

    df = LearningFramework.MultiPeriodData(database,
                                           datetime1, datetime2, factors,
                                           profileFolderName="MultiFactor",
                                           rangeReturnFolderName="HalfYear",
                                           params=params
                                           )

    # print(df.head(20))

    # ---Prepare DataSet---
    dfX = df.drop(columns=["IsSignificant"])
    dfY = df[["IsSignificant"]]

    #
    LearningFramework.Train(dfX, dfY)

if __name__ == '__main__':
    # ---Connect Database---
    config = Config.Config()
    database = config.DataBase("MySQL")

    # ---Test---
    # df = pd.read_csv("d:/Data/TestOutlier.csv")
    # print(df)
    # LearningFramework.Outlier_NSigma(df, 1)
    # # df = LearningFramework.Outlier_Percentile(df, remove=False)
    # print(df)

    # datetime1 = datetime.datetime(2007, 5, 1)
    # datetime2 = datetime.datetime(2019, 5, 1)
    # datetimes = Gadget.GenerateTimeRange_HalfYear(datetime1, datetime2)

    # ---Analysis---
    # ---Fix Leverage---
    # datetime1 = datetime.datetime(2010, 3, 31)
    # factors = ["Leverage"]
    # df = General.LoadFactorProfile(database, factors, datetime1)
    # General.PlotHistgram(df, "Leverage")
    # #
    # dfSorted = df.sort_values(by="Leverage", ascending=False)
    # print(dfSorted)

    # ---Factors---
    factors = []
    # Earning
    factors.append("ProfitMargin_NetIncome2_LYR")
    # factors.append("ProfitMargin_NetIncome2_TTM")
    factors.append("ROE_NetIncome2_LYR")
    factors.append("ROE_NetIncome2_TTM")
    # Earning Variable

    # Value
    factors.append("EarningToPrice_LYR")
    factors.append("EarningToPrice_TTM")
    factors.append("PB_LF")

    # Cashflow (Ver2 add)
    factors.append("CashEarningMinusEarning_LYR")
    factors.append("CashEarningMinusEarning_TTM")
    factors.append("FCFToTotalIncome_LYR")
    factors.append("FCFToTotalIncome_TTM")

    # Growth
    factors.append("Growth_CAGR_TotalRevenue_1Yr")
    factors.append("Growth_CAGR_NetIncome2_1Yr")
    factors.append("Growth_YoY_TotalRevenue")
    factors.append("Growth_YoY_NetIncome2")

    # Leverage (Ver2 add)
    # Capital
    factors.append("Leverage")
    # factors.append("CapLeverage")
    factors.append("CurrentRatio")

    # Size
    # factors.append("LnCap")
    #
    # Operation (Ver2 add)
    factors.append("AssetTurnover_LYR")
    factors.append("AssetTurnover_TTM")

    # Momentum (Ver2 add)
    factors.append("Momentum_20D")
    factors.append("Bias_20D")

    # Volatility (Ver2 add)
    factors.append("Volatility_Annually")
    factors.append("CAPMBeta_Annually")

    # factors = ["CAPMBeta_Annually"] # "CAPMBeta_Annually"
    # Liquidity (Ver2 add)

    # Dividend

    # CheckFactors(database)

    # ExportFactors(database)

    Train(database, factors)